﻿using System.Collections.Concurrent;

namespace FireChat.Share.Web.Package;



/// <summary>
/// 数据包缓存
/// </summary>
public class PackageBuffer<T> where T : IPackage
{
    /// <summary>
    /// 缓存集合
    /// </summary>
    private readonly ConcurrentBag<T> _buffer = new();



    /// <summary>
    /// 添加一个包到缓存
    /// </summary>
    public void Add(T package)
    {
        _buffer.Add(package);
    }

    /// <summary>
    /// 获取一个包 不存在先重新尝试 不行返回null
    /// </summary>
    /// <param name="predicate">筛选包的条件</param>
    /// <param name="retryCount">重试次数</param>
    /// <param name="awaitSeconds">每次间隔秒数</param>
    public Task<T?> GetAsync(Predicate<T> predicate, int retryCount = 30, double awaitSeconds = 0.5)
    {
        async Task<T?> method()
        {
            for (int i = 1; i <= retryCount; i++)
            {
                var server_package = TakePackage(predicate);
                if (server_package != null)
                {
                    return server_package;
                }

                await Task.Delay(TimeSpan.FromSeconds(awaitSeconds));
            }

            return default;
        }

        return Task.Run(method);
    }



    /// <summary>
    /// 筛选出来一个符合条件的包并移除缓存
    /// </summary>
    private T? TakePackage(Predicate<T> predicate)
    {
        foreach (var package in _buffer)
        {
            if (!predicate(package))
            {
                continue;
            }

            if (_buffer.TryTake(out var select_package))
            {
                return select_package;
            }
        }

        return default;
    }
}
